home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char SccsId[]= "@(#)graph_query.c V1.8 3/13/95";
- #endif
- /*
- | file name - graph_query.c
- |=========================================================================
- |
- | This is an example program of how users can get an exact value off a
- | particular point inside a graph. The program allows a user to display
- | one of three types of graphs (line, point, or strip ) which display 50
- | data points each time they update. Updates occur when the user picks
- | on an 'Update' button. In between updates, the user can pick inside
- | the graph's data area and then based on the location of the cursor, a
- | vertical line is dropped at that time slot. A digits graph is used to
- | displays the exact value for that particular point. The graphs are
- | queried to retrieve the selected data slot and the data value of the
- | vdp at the selected point. This is accomplished using the feedback
- | query flags defined for the module VPdgdfquery.
- |
- |=========================================================================
- */
- #include <windows.h>
- /*
- * DV-Tools header files
- */
- #include "std.h" /* <stdio.h> etc., scalar & macro definitions */
- #include "dvstd.h" /* public types & constants */
- #include "dvtools.h" /* constants used by T routines */
- #include "dvGR.h" /* constants used by window mgt & GR routines */
- #include "VOstd.h" /* constants used by VO & VOob routines */
- #include "Tfundecl.h" /* T routines (screens, drawports & views) */
- #include "VOfundecl.h" /* VO routines (objects) */
- #include "VUerfundecl.h" /* VUer routines (event handling routines) */
- #include "VPfundecl.h" /* VP routines (put info for dgp & vdp) */
- #include "VGfundecl.h" /* VG routines (get info from dgp & vdp) */
- #include "GRfundecl.h" /* GR routines (interface to display device) */
-
- /* Constants */
- #define DVPATH (char *)NULL
- #define DISPFORMS_STB (char *)NULL
- #define DVDEVICE (char *)NULL
- #define DVCOLORTABLE (char *)NULL
- #define VIEW_NAME "graph_query.v"
- #define SCREEN_VIEWPORT (RECTANGLE *)NULL
- #define DRAWING_VIEWPORT (RECTANGLE *)NULL
-
- /* Defines */
- #define MAIN_MENU 0
- #define GRAPH_MENU 1
- #define UPDATE 0
- #define QUIT 1
- #define NUM_GRAPHS 3
- #define LINE_GRAPH 0
- #define POINT_GRAPH 1
- #define STRIP_CHART 2
- #define NO_PREV_GRAPH (-1)
- #define FIRST_SLOT 1
-
- /* Define the graph information structure */
- typedef struct
- {
- OBJECT graph; /* Handle to graph object */
- DATAGROUP dgp; /* Handle to graph's data group pointer */
- int slots; /* Number of slots in the graph */
- } GRAPH_INFO;
-
- /* Globals */
- DRAWPORT drawport; /* how & where to display picture */
- VIEW view; /* picture representation of the view file */
- OBJECT CurrentValGraph; /* digit graph to display data value */
- float *CurrentValue; /* ptr to buffer for digit graph */
- int MainSel, /* buffer for main menu selection value */
- CurrGraph, /* index representing the current graph */
- PrevGraph, /* index representing the previous graph */
- VpHeight, /* height of graph's data display area */
- MarkerColor, /* color used by line marker */
- MarkerStartX, /* x-coordinate of line marker start pt */
- OldSlotNum; /* previous selected data slot */
- RECTANGLE ScreenVp; /* graph's data display area */
- DV_POINT SlotSize; /* size of single slot in a graph */
- ADDRESS Raster; /* raster array before marker drawn */
- int QuitProgram = NO; /* flag to quit program */
- char *GraphName[NUM_GRAPHS] = {"line", "points", "strip"};
- GRAPH_INFO GraphInfo[NUM_GRAPHS]; /* saved information about graphs */
-
- /* Functions defined in graph_query.c */
- void DisplaySlotValue V_P_((DV_POINT *picked_point));
- void UpdateScreen V_P_((int GraphChange));
- void InitStructures V_P_((void));
- void EraseLine V_P_((void));
- void DrawLineAtSlot V_P_((int selected_slot));
- int EventHandler V_P_((OBJECT client, EVENT_REQUEST request, int label, OBJECT loc, ADDRESS args));
-
- /*------------------
- * DisplaySlotValue -- Determine the data value represented
- * on the graph at the user selected point. Update the
- * digit graph to display this data value.
- */
- void
- DisplaySlotValue (picked_point)
- DV_POINT *picked_point;
- {
- double dvalue; /* value represented a selected point */
- V_Q_PICK_VDP query_vdp; /* query vdp for data information */
-
- /*
- * VPdgdfquery: Queries a display formatter for information
- *
- * V_Q_DATA_VALUE: Gets a value of the vdp displayed
- * at the point.
- *
- * Obtain the data value of the vdp at the selected point.
- * In this example, all graphs have only one variable being
- * displayed. If a graph displays more than one variable
- * then the below code would need to be changed to
- * obtain a data value for each of the variables at the
- * picked point.
- */
- query_vdp.vdp = (V_Q_VDP *) S_ALLOC (sizeof (V_Q_VDP));
- query_vdp.location = *picked_point;
- query_vdp.vdp->vdp = VGdgvd (GraphInfo[CurrGraph].dgp, 1);
- query_vdp.vdp->index = 1;
- VPdgdfquery (GraphInfo[CurrGraph].dgp, V_Q_DATA_VALUE,
- (ADDRESS) & query_vdp, (ADDRESS) & dvalue);
-
- /*
- * Set the value to be displayed then update the digit graph.
- */
- *CurrentValue = (float) dvalue;
- TdpDrawNextObject (drawport, CurrentValGraph);
- S_FREE ((ADDRESS)query_vdp.vdp);
-
- }
-
-
- /*--------------
- * UpdateScreen -- Update the screen by displaying the selected
- * graph. The line graph is the default graph to be displayed.
- * The display of the graph involves erasing and deleting the
- * previously displayed graph from the drawing if one exists
- * and adding the newly selected graph to the drawing, reading
- * data and displaying the graph. The graph is updated for
- * for the number of samples assigned to the graph.
- */
- void
- UpdateScreen (GraphChange)
- int GraphChange;
- {
- OBJECT drawing; /* graphical representation of screen */
- DV_POINT fake_selected_point; /* fake selection point */
- int SlotOffset, /* offset used to center marker on slot */
- number_of_updates, /* number of times to update the display */
- i; /* counter */
-
- /* Obtain the drawing object from the view */
- drawing = TviGetDrawing (view);
-
- /* Erase old indicator line if there is one */
- if (Raster)
- EraseLine ();
-
- /*
- * Erase and draw graphs as needed: Erase previous
- * graph if only the graph has changed since the last
- * update and there is actually a previous graph.
- * Then, delete the old graph from the drawing.
- */
- if (PrevGraph != NO_PREV_GRAPH && GraphChange)
- {
- TdpEraseObject (drawport, GraphInfo[PrevGraph].graph);
- VOdrObDelete (drawing, GraphInfo[PrevGraph].graph);
- }
-
- /*
- * Add the new graph to the drawing, read an iteration of data,
- * and draw the graph.
- */
- if (GraphChange)
- {
- VOdrObAdd (drawing, GraphInfo[CurrGraph].graph);
- TviReadData (view);
- TdpDrawObject (drawport, GraphInfo[CurrGraph].graph);
- }
-
- /*
- * Read enough data to fill up the graph. This is based on the
- * number of samples assigned for the graph.
- */
- number_of_updates = (GraphChange) ? GraphInfo[CurrGraph].slots - 1
- : GraphInfo[CurrGraph].slots;
- for (i = 0; i < number_of_updates; i++)
- {
- TviReadData (view);
- TdpDrawNextObject (drawport, GraphInfo[CurrGraph].graph);
- }
-
- /*
- * Once the graph has been drawn and updated, obtain the slot size
- * and data display area information.
- */
- VPdgdfquery (GraphInfo[CurrGraph].dgp,
- V_Q_SLOTSIZE, (ADDRESS)NULL, (ADDRESS) & SlotSize);
- VPdgdfquery (GraphInfo[CurrGraph].dgp,
- V_Q_DATAVP, (ADDRESS)NULL, (ADDRESS) & ScreenVp);
-
- /*
- * Determine the height of the data display area which will be
- * used when getting the raster before the line marker is
- * drawn. The line marker designates the selected data slot.
- * Next, draw the indicator line at the first slot of the graph.
- */
- VpHeight = ScreenVp.ur.y - ScreenVp.ll.y;
- if (CurrGraph != STRIP_CHART)
- DrawLineAtSlot (FIRST_SLOT);
- else
- DrawLineAtSlot (0);
-
- /*
- * Display the slot value for the first slot in the graph.
- * Create a fake selection point to obtain the data value at
- * the graph's first data slot.
- */
- if (CurrGraph != STRIP_CHART)
- SlotOffset = SlotSize.x / 2;
- else
- SlotOffset = 0;
- fake_selected_point.x = ScreenVp.ll.x + SlotOffset;
- fake_selected_point.y = ScreenVp.ll.y;
- DisplaySlotValue (&fake_selected_point);
-
- /* Set the previous graph to the current graph */
- PrevGraph = CurrGraph;
- }
-
-
- /*----------------
- * InitStructures -- The module initializes necessary structures
- * used throughout the program based on information retrieved
- * from the view. The marker object, graph objects and input
- * objects are obtained and service result events are posted
- * for the input objects.
- */
- void InitStructures ()
- {
- OBJECT drawing, /* graphical representation of screen */
- object; /* graphical object */
- DATAGROUP dgp; /* datagroup pointer of digits graph */
- VARDESC vdp; /* variable descriptor of digits graph */
- ADDRESS *vdplist; /* variable descriptor list for input objects */
- int numvars, /* number of vdps in list */
- i; /* counter */
-
- /*
- * TviGetDrawing: Gets a view's drawing object
- */
- drawing = TviGetDrawing (view);
-
- /*
- * Fill the GRAPH_INFO structure with the information on each
- * graph which may be displayed. The data group pointer and
- * slot count (samples) are saved in this structure.
- * The graphs are deleted from the drawing since only one will
- * ever be displayed at a time. Note: the reference count of
- * each object is increased before deleting the object from
- * the drawing. This is done to prevent the object from being
- * removed from the heap. The currently selected graph will
- * be added back to the drawing which facilitates redrawing
- * for expose or resize events.
- */
- for (i = 0; i < NUM_GRAPHS; i++)
- {
- GraphInfo[i].graph = TdrGetNamedObject (drawing, GraphName[i]);
- GraphInfo[i].dgp = VOdgGetDgp (GraphInfo[i].graph);
- GraphInfo[i].slots = VGdgslots (GraphInfo[i].dgp);
- VOobReference (GraphInfo[i].graph);
- VOdrObDelete (drawing, GraphInfo[i].graph);
- }
-
- /*
- * Obtain the digit graph which will be used to display
- * the picked value. Save the buffer pointer of the
- * data source variable attached to the graph.
- */
- CurrentValGraph = TdrGetNamedObject (drawing, "digits");
- dgp = VOdgGetDgp (CurrentValGraph);
- vdp = VGdgvd (dgp, 1);
- CurrentValue = (float *) TdsvGetBuffer (TvdGetDataSourceVariable (vdp));
-
- /*
- * Rebind the graph menu vdp to the variable CurrGraph,
- * set the variable type to be integer and post a service
- * result request which will monitor selections in the
- * graph menu. CurrGraph will represent the user's
- * selection for the particular graph to be displayed.
- */
- object = TdrGetNamedObject (drawing, "graph menu");
- VOinGetVarList (object, &vdplist, &numvars);
- TvdPutBuffer (vdplist[0], (ADDRESS) & CurrGraph);
- VPvdtype (vdplist[0], V_I_TYPE);
- VUerServiceResultPost ((OBJECT) GRAPH_MENU, EventHandler,
- (ADDRESS) NULL, 0, object, (int)INPUT_DONE, (int)GRAPH_MENU);
-
- /*
- * Rebind the main menu to the variable MainSel, set the
- * variable type to be integer and post a service result
- * request which will monitor selections in the main menu.
- * The main menu selections are Update and Quit.
- */
- object = TdrGetNamedObject (drawing, "main menu");
- VOinGetVarList (object, &vdplist, &numvars);
- TvdPutBuffer (vdplist[0], (ADDRESS) & MainSel);
- VPvdtype (vdplist[0], V_I_TYPE);
- VUerServiceResultPost ((OBJECT) MAIN_MENU, EventHandler,
- (ADDRESS) NULL, 0, object, (int)INPUT_DONE, (int)MAIN_MENU);
-
- /*
- * GRrgbtoindex: Gets an index of a color in the color
- * lookup table. (255 255 0 = yellow)
- * Set the marker color which will be used for raster draws.
- */
- GRrgbtoindex (255, 255, 0, &MarkerColor);
- }
-
- /*-----------
- * EraseLine -- Restore the raster taken before drawing the
- * line marker. This raster will remove the drawn line
- * marker from the display.
- */
- void EraseLine ()
- {
- DV_POINT endpt1;
-
- /*
- * GRrasdraw: Draws a raster to the selected device
- * GRrasfree: Frees allocated storage area for raster
- *
- * If a raster is defined, then restore it and free it.
- */
- if (Raster)
- {
- endpt1.x = MarkerStartX;
- endpt1.y = ScreenVp.ll.y;
- GRrasdraw (Raster, &endpt1);
- GRrasfree (Raster);
- Raster = (ADDRESS) NULL;
- }
- }
-
- /*----------------
- * DrawLineAtSlot --
- */
- void
- DrawLineAtSlot (selected_slot)
- int selected_slot;
- {
- DV_POINT endpt1, endpt2;
- int SlotOffset;
-
- /*
- * Decrease the past slot number by one. The selected
- * slot number is a 1-based index. Subtracting one
- * is done since we will be determining from the
- * lower left corner of the data display area where
- * to draw the line marker.
- *
- * If the current graph is the STRIP_CHART then do not
- * subtract one since the data flows from the right to
- * left. The data value to be returned based on the
- * location will be the data value to the right of the
- * point. Therefore, we do not subtract one from the
- * number.
- */
- if (CurrGraph != STRIP_CHART)
- selected_slot--;
-
- /*
- * The slot offset for most graphs will be half the width
- * of the time slot, i.e. we want to draw the vertical line
- * in the center of the time slot. However for the strip
- * chart, the data points are drawn such that they are located
- * over the left edge of the time slots boundary, so there is
- * no offset.
- */
- if (CurrGraph != STRIP_CHART)
- SlotOffset = SlotSize.x / 2;
- else
- SlotOffset = 0;
-
- /*
- * If there is a raster is already defined, then we need erase the
- * line and free the old raster.
- */
- if (Raster)
- EraseLine ();
-
- /* Determine the start point for the line marker. */
- endpt1.x = ScreenVp.ll.x + (SlotSize.x * selected_slot) + SlotOffset;
- endpt1.y = ScreenVp.ll.y;
-
- /*
- * Save the slot number and x value, get the raster where the
- * line will be drawn, and draw the line in the marker color.
- */
- MarkerStartX = endpt1.x;
- GRrasget (&endpt1, 1, VpHeight, &Raster);
- GRcolor (MarkerColor);
- endpt2.x = endpt1.x;
- endpt2.y = ScreenVp.ur.y;
- GRmove_and_vector (&endpt1, &endpt2);
- GRflush ();
- }
-
-
- /*--------------
- * EventHandler -- Perform the appropriate action based on
- * the user's interaction with the particular menu
- * input object. This function is called to control the
- * main menu and the graph selection menu.
- *
- */
- /*ARGSUSED*/
- int
- EventHandler (client, request, label, loc, args)
- OBJECT client;
- EVENT_REQUEST request;
- int label;
- OBJECT loc;
- ADDRESS args;
- {
-
- switch (label)
- {
- /* New graph selected */
- case GRAPH_MENU:
- UpdateScreen (YES);
- break;
-
- /*
- * Check the main menu selection: call UpdateScreen if the user
- * selected to update the graph; otherwise the user selected to
- * quit the program.
- */
- case MAIN_MENU:
- if (MainSel == UPDATE)
- UpdateScreen (NO);
- else
- QuitProgram = YES;
- break;
- }
-
- return (int) INPUT_USED;
- }
-
- /*
- * MAIN PROGRAM
- */
- int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow )
- {
- INT argc = 0;
- CHAR **argv;
- /*
- * program arguments
- * argv[1] - display device name (default is to use DVDEVICE)
- */
-
- /* Define & initialize device name and view filename */
- char *device_name = DVDEVICE; /* default device name */
- char *view_name = VIEW_NAME; /* default view name */
-
- OBJECT screen, /* display device, the window */
- location, /* the event representation */
- drawing; /* graphical representation of screen */
- DV_POINT *cur_loc; /* screen coordinates of selected location */
- int i, /* counter */
- slot_num; /* data slot number */
- int ResizeOccured = NO; /* flag indicating resize event occurred */
-
- /*-----------------
- * Initialization
- *
- * TInit: perform the initialization of DV-Tools
- * TInit reads your configuration file and any
- * environment variables or logical names set.
- */
- make_argv(&argc,&argv,GetCommandLine());
- TInit( DVPATH, DISPFORMS_STB );
-
- /*
- * TscOpenSet: opens a device as a screen object using
- * specified attributes
- *
- * Set exposure block to YES to insure the window
- * is ready for drawing when TdpDraw is called.
- */
- if (argc > 1)
- device_name = argv[1];
- screen = TscOpenSet (device_name, DVCOLORTABLE,
- V_X_EXPOSURE_BLOCK, YES,
- V_ACTIVE_CURSOR, V_END_OF_LIST);
- if (!screen)
- {
- printf ("Must specify device on command line or");
- printf (" in DataViews configuration file.\n");
- S_EXIT (EXIT_ERR);
- }
-
- /*
- * VOscWinEventMask: sets the screen's window event mask
- */
- VOscWinEventMask ((ULONG) V_KEYPRESS | V_BUTTONPRESS |
- V_MOTIONNOTIFY | V_EXPOSE | V_RESIZE,
- (ULONG) 0);
-
- /*
- * TviLoad: Load a view in from a file,
- * user supplied view or default view of buffer.v
- */
- view = TviLoad (view_name);
- if (!view)
- {
- printf ("Could not load view from file ");
- printf ("%s.\n", view_name);
- S_EXIT (EXIT_ERR);
- }
-
- /*
- * TdpCreate: Create a drawport.
- * The drawport is attached to the screen object
- * specified while view specifies the view to be
- * displayed on the screen.
- */
- drawport = TdpCreate (screen, view, SCREEN_VIEWPORT, DRAWING_VIEWPORT);
-
- /* Initialize global variables */
- PrevGraph = NO_PREV_GRAPH;
- CurrGraph = 0;
- slot_num = 0;
- OldSlotNum = FIRST_SLOT;
- Raster = (ADDRESS) NULL;
-
- /*
- * Prepare the view, open the data sources, draw
- * the drawport, and update the screen.
- */
- InitStructures ();
- TviOpenData (view);
- TdpDraw (drawport);
- UpdateScreen (YES);
-
- /*---------------------
- * Control Loop
- *
- * Poll the event queue for window events. Events
- * occurring within input objects will be handled
- * through the event request handler VUerHandleLocEvent.
- */
- FOREVER
- {
- /*
- * VOloWinEventPoll: Poll for the next window event.
- * The polling mode used is V_WAIT.
- * Therefore, VOloWinEventPoll does not
- * return until a masked event is
- * generated. V_WAIT always produces
- * a valid location object.
- */
- location = VOloWinEventPoll (V_WAIT);
-
- /*
- * VOloType: returns the type of event. These types
- * match event types specified in VOscWinEventMask.
- */
- switch (VOloType (location))
- {
-
- case V_RESIZE:
- /*
- * The window size has been changed.
- * TscReset: Resets all screen drawports after
- * window resizing
- * Free the raster taken for the line drawn at the
- * selected slot. The screen will be redrawn so the
- * raster is no longer valid.
- */
- TscReset (screen);
- GRrasfree (Raster);
- Raster = (ADDRESS) NULL;
- ResizeOccured = YES;
- break;
-
- case V_EXPOSE:
- /*
- * VOloRegion: Returns a rectangle representing the
- * exposed region on the screen.
- * TscRedraw: After erasing, redraws all the drawports
- * in the screen.
- * A portion of the window has been exposed and needs
- * to be redrawn.
- */
- TscRedraw (screen, VOloRegion (location));
-
- /* Obtain the new information concerning the data vp area of the graph.*/
- if (ResizeOccured == YES)
- {
- /* GraphInfo[CurrGraph].dgp; */ /* statement with no effect */
- VPdgdfquery (GraphInfo[CurrGraph].dgp,
- V_Q_DATAVP, (ADDRESS)NULL, (ADDRESS) & ScreenVp);
- VPdgdfquery (GraphInfo[CurrGraph].dgp,
- V_Q_SLOTSIZE, (ADDRESS)NULL, (ADDRESS) & SlotSize);
- VpHeight = ScreenVp.ur.y - ScreenVp.ll.y;
- ResizeOccured = NO;
- }
-
- DrawLineAtSlot (OldSlotNum);
- break;
-
- case V_BUTTONPRESS:
- case V_KEYPRESS:
- if (VUerHandleLocEvent (location) == INPUT_UNUSED)
- {
- /*
- * If the screen location of the cursor is within the data area
- * of the graph, then determine which data slot was selected.
- * If the data slot has changed from the previous selection
- * then draw a new line marker and update the digit graph with
- * the data value at the selected slot.
- *
- * V_Q_SLOT_AT_LOCATION: Gets the 1-based index of the slot
- * at the point.
- */
- cur_loc = VOloScpGet (location);
- if (ScreenVp.ll.x <= cur_loc->x && cur_loc->x <= ScreenVp.ur.x &&
- ScreenVp.ll.y <= cur_loc->y && cur_loc->y <= ScreenVp.ur.y)
- {
- VPdgdfquery (GraphInfo[CurrGraph].dgp,
- V_Q_SLOT_AT_LOCATION, (ADDRESS)cur_loc,
- (ADDRESS) &slot_num);
- if (slot_num != -1 && slot_num != OldSlotNum)
- {
- OldSlotNum = slot_num;
- DrawLineAtSlot (slot_num);
- DisplaySlotValue (cur_loc);
- }
- }
- }
- break;
- }
- if (QuitProgram == YES)
- break;
- }
-
- /*
- * Delete the current graph from the drawing. Then, dereference
- * all of the graph objects which will remove them from the heap.
- * This frees the memory for these objects. It is the responsibility
- * of the application to free the memory of all objects which are
- * maintained outside of the drawing object
- */
- drawing = TviGetDrawing (view);
- VOdrObDelete (drawing, GraphInfo[CurrGraph].graph);
- for (i = 0; i < NUM_GRAPHS; i++)
- VOobDereference (GraphInfo[i].graph);
-
- /*--------------------
- * Termination
- *
- * TscErase: Erase the entire screen in the default
- * background color
- * TdpDestroy: Destroy the drawport,
- * TviCloseData: Close the data sources of the view
- * TviDestroy: Destroy the view, freeing the allocated memory
- * TscCloseCurrentScreen: Close the current display screen
- * TTerminate: Perform the clean-up for DV-Tools
- */
- TscErase (screen);
- TdpDestroy (drawport);
- TviCloseData (view);
- TviDestroy (view);
- TscCloseCurrentScreen ();
- TTerminate ();
- return EXIT_OK;
- }
-